package han.Chensing.CCirnosLibrary.map;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;

import han.Chensing.CCirnosLibrary.CCirnoLibrary;
import han.Chensing.CCirnosLibrary.util.RegexUtil;
import han.Chensing.CCirnosLibrary.util.SerialUtil;

public class ItemMap implements Serializable {

    private static final long serialVersionUID= 1145141919810L;

    private final ItemNode rootNode;
    private boolean hasMagic;

    public ItemMap(){
        this.rootNode=new ItemNode();
        rootNode.getItemFlag().addFlag("root");
        rootNode.setName("ROOT");
        rootNode.setLink("");
        rootNode.setOriginalName("ROOT");
        rootNode.setFolder(true);
        rootNode.setRootNode(true);
    }

    public void analyze(List<String> strings,String rootLink){
        Stack<ItemNode> nodeStack=new Stack<>();
        nodeStack.push(rootNode);
        Pattern flagPattern = Pattern.compile("[&][&][&].*[&][&][&]");
        Pattern linkPattern = Pattern.compile("[$][#].*[$][#]");
        Pattern titlePattern= Pattern.compile("[~][`].*[`][~]");
        Pattern originalPattern = Pattern.compile("[<][-][<].*[>][-][>]");
        boolean hasMagic=false;
        for (String line : strings) {
            if (line.equals(CCirnoLibrary.INDEX_MAGIC)) {
                hasMagic=true;
                continue;
            }
            ItemNode parent = nodeStack.peek();
            if (line.startsWith("#"))
                switch (line.charAt(1)) {
                    case '>':
                        ItemNode itemNode = new ItemNode();
                        String name = line.substring(2);
                        itemNode.setName(name);
                        itemNode.setOriginalName(name);
                        itemNode.setFolder(true);
                        itemNode.setRootLink(rootLink);
                        parent.getChildNodes().add(itemNode);
                        nodeStack.push(itemNode);
                        break;
                    case '<':
                        nodeStack.pop();
                        break;
                }
            String flags = RegexUtil.getFirstMatch(line, flagPattern,3);
            String link = RegexUtil.getFirstMatch(line, linkPattern,2);
            String title = RegexUtil.getFirstMatch(line, titlePattern,2);
            String originalName = RegexUtil.getFirstMatch(line, originalPattern, 3);
            if (!(flags!=null||link!=null||title!=null||originalName!=null))
                continue;
            ItemNode itemNode = new ItemNode();
            if (flags!=null) {
                String[] flagsArray = flags.split("\\|");
                for (String flag : flagsArray)
                    itemNode.getItemFlag().addFlag(flag);
            }
            itemNode.setName(title);
            itemNode.setLink(link);
            itemNode.setParent(parent);
            itemNode.setOriginalName(originalName);
            itemNode.setRootLink(rootLink);
            parent.getChildNodes().add(itemNode);
        }
        this.hasMagic=hasMagic;
    }

    public ItemNode getRootNode() {
        return rootNode;
    }

    public void unload(){
        rootNode.clear();
        System.gc();
    }

    public static ItemMap fromStream(InputStream inputStream) throws IOException, ClassNotFoundException {
        return SerialUtil.fromStream(inputStream,ItemMap.class);
    }

    public static void toStream(ItemMap map,OutputStream outputStream) throws IOException {
        SerialUtil.toStream(map,outputStream);
    }

    public boolean isHasMagic() {
        return hasMagic;
    }

    public void setHasMagic(boolean hasMagic) {
        this.hasMagic = hasMagic;
    }
}
